package com.innovation.wjrpc.handle;

import com.innovation.wjrpc.codec.Decoder;
import com.innovation.wjrpc.codec.Encoder;
import com.innovation.wjrpc.protocol.Request;
import com.innovation.wjrpc.protocol.Response;
import com.innovation.wjrpc.protocol.StatusCheck;
import com.innovation.wjrpc.server.ServiceInstance;
import com.innovation.wjrpc.server.ServiceInvoker;
import com.innovation.wjrpc.server.ServiceManager;
import com.innovation.wjrpc.transport.NettyHandler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author innoyiya
 * @date 2021/9/8 19:00
 */
@ChannelHandler.Sharable
@Slf4j
@AllArgsConstructor
public class NettyRequestHandler extends NettyHandler {
    private Decoder decoder;
    private Encoder encoder;
    private ServiceManager serviceManager;
    private ServiceInvoker serviceInvoker;


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg){
        ByteBuf in = (ByteBuf) msg;
        Response response = new Response();
        byte[] data = new byte[in.readableBytes()];
        System.out.println(data.length);
        in.readBytes(data);
        Request request = decoder.decode(data, Request.class);
        response.setId(request.getId());

        ctx.channel().eventLoop().execute(() -> {
            ServiceInstance instance = serviceManager.lookUp(request);
            Object o = serviceInvoker.invoke(instance, request);
            StatusCheck.setInHand(response);
            response.setData(o);
            response.setMessage("ok");
            StatusCheck.setTreated(response);
            System.out.println("response = " + response.toString());
            // todo 异常处理

            ByteBuf byteBuf = Unpooled.buffer();
            byteBuf.writeBytes(encoder.encode(response));

            ctx.writeAndFlush(byteBuf).addListener(future -> System.out.println("already hand"));

        });
        if (!StatusCheck.isOriginal(response)) return;
        response.setMessage("receive");
        StatusCheck.setInHand(response);
        ByteBuf byteBuf = Unpooled.buffer();
        byteBuf.writeBytes(encoder.encode(response));
        System.out.println(byteBuf.readableBytes());
        ctx.writeAndFlush(byteBuf);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("already receive data");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
